home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
machserver
/
1.098
/
lfs
/
lfsBlockIO.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-29
|
8KB
|
256 lines
/*
* lfsBlockIO.c --
*
* Routines for handling block allocate and access of files in a
* LFS file system. This routines are used by the cache code or
* read and allocate files.
*
* Copyright 1989 Regents of the University of California
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. The University of California
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#ifndef lint
static char rcsid[] = "$Header: /sprite/src/kernel/lfs/RCS/lfsBlockIO.c,v 1.7 91/06/29 17:01:02 mendel Exp $ SPRITE (Berkeley)";
#endif /* not lint */
#include <sprite.h>
#include <lfs.h>
#include <lfsInt.h>
#include <fs.h>
#include <fsutil.h>
#include <fsio.h>
#include <fsioFile.h>
#include <fslcl.h>
#include <fscache.h>
#include <fsdm.h>
#include <fsStat.h>
/*
*----------------------------------------------------------------------
*
* Lfs_FileBlockRead --
*
* Read in a cache block. This routine uses the files'
* indexing structure to locate the file block on disk.
* This always attempts to read in a full block, but will read
* less if at the last block and it isn't full. In this case,
* the remainder of the cache block is zero-filled.
*
* Results:
* The results of the disk read.
*
* Side effects:
* The blockPtr->blockSize is modified to
* reflect how much data was actually read in. The unused part
* of the block is filled with zeroes so that higher levels can
* always assume the block has good stuff in all parts of it.
*
*----------------------------------------------------------------------
*/
ReturnStatus
Lfs_FileBlockRead(domainPtr, handlePtr, blockPtr)
Fsdm_Domain *domainPtr; /* Domain of file. */
register Fsio_FileIOHandle *handlePtr; /* Handle on a local file. */
Fscache_Block *blockPtr; /* Cache block to read in. This assumes
* the blockNum, blockAddr (buffer area)
* and blockSize are set. This modifies
* blockSize if less bytes were read
* because of EOF. */
{
Lfs *lfsPtr = LfsFromDomainPtr(domainPtr);
register Fsdm_FileDescriptor *descPtr;
register offset;
register int numBytes;
LfsDiskAddr diskAddress;
ReturnStatus status;
LFS_STATS_INC(lfsPtr->stats.blockio.reads);
status = SUCCESS;
blockPtr->blockSize = 0;
numBytes = FS_BLOCK_SIZE;
offset = blockPtr->blockNum * FS_BLOCK_SIZE;
/*
* Is a logical file read. Round the size down to the actual
* last byte in the file.
*/
descPtr = handlePtr->descPtr;
if (offset > descPtr->lastByte) {
goto exit;
} else if (offset + numBytes - 1 > descPtr->lastByte) {
numBytes = descPtr->lastByte - offset + 1;
}
status = LfsFile_GetIndex(handlePtr, offset / FS_BLOCK_SIZE, 0,
&diskAddress);
if (status != SUCCESS) {
printf("Lfs_FileBlockRead: Could not setup indexing\n");
goto exit;
}
if (!LfsIsNilDiskAddr(diskAddress)) {
/*
* Read in the block. Specify the device, the fragment index,
* the number of fragments, and the memory buffer.
*/
int ioSize =
LfsBlocksToBytes(lfsPtr, LfsBytesToBlocks(lfsPtr, numBytes));
LfsCheckRead(lfsPtr, diskAddress, numBytes);
status = LfsReadBytes(lfsPtr, diskAddress, ioSize, blockPtr->blockAddr);
LFS_STATS_ADD(lfsPtr->stats.blockio.bytesReads, ioSize);
} else {
/*
* Zero fill the block. We're in a 'hole' in the file.
*/
#ifdef STATS
fs_Stats.blockCache.readZeroFills++;
#endif
bzero(blockPtr->blockAddr, numBytes);
}
#ifdef STATS
Fs_StatAdd(numBytes, fs_Stats.gen.fileBytesRead,
fs_Stats.gen.fileReadOverflow);
#ifdef SOSP91
if (proc_RunningProcesses[0] != (Proc_ControlBlock *) NIL) {
if ((proc_RunningProcesses[0]->state == PROC_MIGRATED) ||
(proc_RunningProcesses[0]->genFlags &
(PROC_FOREIGN | PROC_MIGRATING))) {
Fs_StatAdd(numBytes, fs_SospMigStats.gen.fileBytesRead,
fs_SospMigStats.gen.fileReadOverflow);
}
}
#endif SOSP91
#endif
exit:
/*
* Define the block size and error fill leftover space.
*/
if (status == SUCCESS) {
blockPtr->blockSize = numBytes;
}
if (blockPtr->blockSize < FS_BLOCK_SIZE) {
#ifdef STATS
fs_Stats.blockCache.readZeroFills++;
#endif
bzero(blockPtr->blockAddr + blockPtr->blockSize,
FS_BLOCK_SIZE - blockPtr->blockSize);
}
return(status);
}
/*
*----------------------------------------------------------------------
*
* Lfs_FileBlockWrite --
*
* Write out a cache block. Since lfs maintains its own cache
* write back mechanism, this routines should never be called.
*
* Results:
* FAILURE
*
* Side effects:
* It panic's.
*
*----------------------------------------------------------------------
*/
/*ARGSUSED*/
ReturnStatus
Lfs_FileBlockWrite(domainPtr, handlePtr, blockPtr)
Fsdm_Domain *domainPtr;
Fsio_FileIOHandle *handlePtr; /* I/O handle for the file. */
Fscache_Block *blockPtr; /* Cache block to write out. */
{
panic("Lfs_FileBlockWrite called\n");
return FAILURE;
}
/*
*----------------------------------------------------------------------
*
* Lfs_BlockAllocate --
*
* Allocate disk space for the given file. This routine only allocates
* one block beginning at offset and going for numBytes.
*
* Results:
* SUCCESS or FS_NO_DISK_SPACE
*
*
* Side effects:
* The file descriptor is modified to contain pointers to the allocated
* blocks. Also *blockAddrPtr is set to the block that was allocated.
*
*----------------------------------------------------------------------
*/
ReturnStatus
Lfs_BlockAllocate(domainPtr, handlePtr, offset, numBytes, flags, blockAddrPtr,
newBlockPtr)
Fsdm_Domain *domainPtr; /* Domain of file. */
register Fsio_FileIOHandle *handlePtr; /* Local file handle. */
int offset; /* Offset to allocate at. */
int numBytes; /* Number of bytes to allocate. */
int flags; /* FSCACHE_DONT_BLOCK */
int *blockAddrPtr; /* Disk address of block allocated. */
Boolean *newBlockPtr; /* TRUE if there was no block allocated
* before. */
{
Lfs *lfsPtr = LfsFromDomainPtr(domainPtr);
int newLastByte;
ReturnStatus status;
Boolean dirty = FALSE;
register Fsdm_FileDescriptor *descPtr;
LFS_STATS_INC(lfsPtr->stats.blockio.allocs);
/*
* Block allocates while checkpoints are active. This ensure that
* the LFS cache backend will be able to clean all LFS files from the
* cache. We only need worry about files, directory updates get stopped by
* the dirlog mechanism. In fact, waiting for a checkpoint for a
* directory block allocate causes a possible deadlock because the
* checkpoint waits for directory operations to finish. We also
* use this mechanism to keep from filling up the cache with blocks
* that we can't write out.
*/
descPtr = handlePtr->descPtr;
if (descPtr->fileType != FS_DIRECTORY) {
LfsWaitForCleanSegments(lfsPtr);
}
/*
* First check to see if we can just allocate the bytes.
*/
newLastByte = offset + numBytes - 1;
*blockAddrPtr = FSDM_NIL_INDEX;
status = LfsFile_GrowBlock(lfsPtr, handlePtr, offset, numBytes);
if (status == SUCCESS) {
*newBlockPtr = FALSE;
*blockAddrPtr = offset / FS_BLOCK_SIZE;
if (newLastByte > descPtr->lastByte) {
descPtr->lastByte = newLastByte;
dirty = TRUE;
}
}
if ((status == SUCCESS) && descPtr->firstByte == -1 &&
((descPtr->fileType == FS_NAMED_PIPE) ||
(descPtr->fileType == FS_PSEUDO_DEV) ||
(descPtr->fileType == FS_XTRA_FILE))) {
descPtr->firstByte = 0;
dirty = TRUE;
}
if (dirty) {
descPtr->descModifyTime = Fsutil_TimeInSeconds();
descPtr->flags |= FSDM_FD_SIZE_DIRTY;
}
return(status);
}